import traceback
from datetime import datetime
from flask import Blueprint,request,abort
from flask_restful import reqparse, inputs, Resource, Api, fields, marshal_with
from ...res import output_json
from ....libs.unit import formatDate,vail_email,vail_phone,vail_pwd,make_crypt,make_pwd,abort_msg
from ....models.database import db, auto_commit
from ....models.console.admin import Admin
from ....models.console.roleuser import RoleUser
from ....decorator.consolejwt import console_token

# 蓝图并放入 restful
admin = Blueprint('admin', __name__, url_prefix='/c-api/admin')
api = Api(admin)

# 统一封装 API 返回值
@api.representation('application/json')
def out_json(data, code, headers=None):
    return output_json(data, code, headers=None)

# 封装返回的数据格式
resource_fields = {
    'count' : fields.Integer,
    'list' : fields.List(fields.Nested({
        'name': fields.String,
        'realname': fields.String,
        'email': fields.String,
        'created_at': formatDate(attribute='created_at'),
        'section': fields.Nested({
            'name': fields.String,
            'status': fields.Integer
        }),
        'roles': fields.List(fields.Nested({
            'id': fields.Integer,
            'name': fields.String
        }))
    }))
}


class ListAdmin(Resource):
    @console_token
    @marshal_with(resource_fields, envelope='resource')
    def get(self):
        # 请求验证
        parser = reqparse.RequestParser()
        parser.add_argument('page', type=int,
                            help=' 页码必须填写', location=['form', 'args'], required=True, action='store')
        args = parser.parse_args()
        page = args.get('page')
        with auto_commit():
            lists = Admin.query.order_by(Admin.id.desc()).paginate(
                page, per_page=10, error_out=False)
            c = {'count':lists.total,'list':lists.items}
        return c


# 封装返回的数据格式
resource_name = {
    'id':fields.Integer,
    'name': fields.String,
    'phone': fields.String,
    'realname': fields.String,
    'email': fields.String,
}


class ListAdminName(Resource):
    @console_token
    @marshal_with(resource_name, envelope='resource')
    def get(self):
        with auto_commit():
            status = request.values.get('status',None)
            lists = Admin.query.order_by(Admin.id.desc())
            if status != None:
                lists = lists.filter(Admin.status == status)
            lists = lists.all()
        return lists

class DetailAdmin(Resource):
    @console_token
    @marshal_with(resource_fields, envelope='resource')
    def get(self):
        # 请求验证
        parser = reqparse.RequestParser()
        parser.add_argument('admin_id', type=int,
                            help='管理员 ID 必须填写', location=['form', 'args'], required=True, action='store')
        args = parser.parse_args()
        with auto_commit():
            c = Admin.query.filter(Admin.id == args.get('admin_id')).first()
        return c


class CreateAdmin(Resource):
    @console_token
    def post(self):
        # 请求验证
        parser = reqparse.RequestParser()
        parser.add_argument('section_id', type=inputs.positive,
                            help='部门必须填写', location=['form', 'args'], required=True, action='store')
        parser.add_argument('role_ids', type=str,
                            help='角色必须填写', location=['form', 'args'], required=False, action='store')
        parser.add_argument('name', type=str,
                            help='登录名必须填写', location=['form', 'args'], required=True, action='store')
        parser.add_argument('realname', type=str, help=' 真实姓名必须填写', location=['form', 'args'], required=False, action='store', default='A')
        # 正则验证邮箱
        parser.add_argument('email', type=vail_email, location=[
                            'form', 'args'], required=False, action='store', default='a@a.com')
        parser.add_argument('phone', type=vail_phone, location=[
                            'form', 'args'], required=False, action='store', default='18911223344')
        # 密码包含大小写、数字，6-15 位
        parser.add_argument('password', type=vail_pwd, location=['form', 'args'], required=True, action='store')
        parser.add_argument('status', type=inputs.positive,
                            help='状态标识必须填写', location=['form', 'args'], required=False, action='store', default=1)
        args = parser.parse_args()
        with auto_commit():
            c = Admin()
            c.section_id = args.get('section_id')
            c.name = args.get('name')
            c.realname = args.get('realname')
            c.phone = args.get('phone')
            c.email = args.get('email')
            c.crypt = make_crypt(6)
            c.password = make_pwd(args.get('password'), c.crypt)
            c.status = args.get('status')
            c.lastip = request.remote_addr
            c.lasttime = datetime.now()
            # 先提交的内存，获取提交后的 id
            db.session.add(c)
            db.session.flush()
            role_ids = args.get('role_ids').split(',')
            insert = []
            for i in list(role_ids):
                insert.append(RoleUser(role_id=i,user_id=c.id))
            db.session.add_all(insert)
        return {'resource': ''}


class EditAdmin(Resource):
    @console_token
    def put(self):
        # 请求验证
        parser = reqparse.RequestParser()
        parser.add_argument('admin_id', type=inputs.positive,
                            help=' 管理员ID 必须填写', location=['form', 'args'], required=True, action='store')
        parser.add_argument('section_id', type=inputs.positive,
                            help='部门必须填写', location=['form', 'args'], required=True, action='store')
        parser.add_argument('role_ids', type=str,
                            help='角色必须填写', location=['form', 'args'], required=False, action='store')
        parser.add_argument('realname', type=str,
                            help=' 真实姓名必须填写', location=['form', 'args'], required=False, action='store',default='A')
        # 正则验证邮箱
        parser.add_argument('email', type=vail_email, location=[
                            'form', 'args'], required=False, action='store', default='a@a.com')
        parser.add_argument('phone', type=vail_phone, location=[
                            'form', 'args'], required=False, action='store', default='18911223344')
        parser.add_argument('status', type=inputs.positive,
                            help='状态标识必须填写', location=['form', 'args'], required=False, action='store', default=1)
        args = parser.parse_args()
        with auto_commit():
            c = Admin.query.filter(Admin.id == args.get('admin_id')).one()
            c.section_id = args.get('section_id')
            c.realname = args.get('realname')
            c.phone = args.get('phone')
            c.email = args.get('email')
            c.status = args.get('status')
            # 角色，先清空再添加
            RoleUser.query.filter(RoleUser.user_id == c.id).delete(
                synchronize_session = False)
            role_ids = args.get('role_ids').split(',')
            insert = []
            for i in list(role_ids):
                insert.append(RoleUser(role_id=i, user_id=c.id))
            db.session.add_all(insert)
        return {'resource': ''}
        

# 修改个人信息
class EditSelfAdmin(Resource):
    @console_token
    def put(self):
        # 请求验证
        parser = reqparse.RequestParser()
        parser.add_argument('admin_id', type=inputs.positive,
                            help=' 管理员ID 必须填写', location=['form', 'args'], required=True, action='store')
        parser.add_argument('realname', type=str,
                            help=' 真实姓名必须填写', location=['form', 'args'], required=False, action='store', default='A')
        # 正则验证邮箱
        parser.add_argument('email', type=vail_email, location=[
                            'form', 'args'], required=False, action='store', default='a@a.com')
        parser.add_argument('phone', type=vail_phone, location=[
                            'form', 'args'], required=False, action='store', default='18911223344')
        parser.add_argument('status', type=inputs.positive,
                            help='状态标识必须填写', location=['form', 'args'], required=False, action='store', default=1)
        args = parser.parse_args()
        with auto_commit():
            c = Admin.query.filter(Admin.id == args.get('admin_id')).one()
            c.realname = args.get('realname')
            c.phone = args.get('phone')
            c.email = args.get('email')
            c.status = args.get('status')
        return {'resource': ''}



class PwdAdmin(Resource):
    @console_token
    def put(self):
        # 请求验证
        parser = reqparse.RequestParser()
        parser.add_argument('admin_id', type=inputs.positive,
                            help=' 管理员ID 必须填写', location=['form', 'args'], required=True, action='store')
        parser.add_argument('password', type=vail_pwd,
                            help='密码必须填写', location=['form', 'args'], required=False, action='store')
        args = parser.parse_args()
        with auto_commit():
            c = Admin.query.filter(Admin.id == args.get('admin_id')).one()
            c.crypt = make_crypt(6)
            c.password = make_pwd(args.get('password'),c.crypt)
        return {'resource': ''}


class DeleteAdmin(Resource):
    @console_token
    def delete(self):
        # 请求验证
        parser = reqparse.RequestParser()
        parser.add_argument('admin_id', type=inputs.positive,
                            help=' 管理员 ID 必须填写', location=['form', 'args'], required=True, action='store')
        args = parser.parse_args()
        with auto_commit():
            if args.get('admin_id') == 1:
                return {'message': '超级管理员不能删除'}, 400
            Admin.query.filter(Admin.id == args.get('admin_id')).delete()
            # 同时删除权限
            RoleUser.query.filter(RoleUser.user_id == args.get(
                'admin_id')).delete(synchronize_session=False)
        return {'resource': ''}


api.add_resource(ListAdmin, '/list')
api.add_resource(ListAdminName, '/listname')
api.add_resource(CreateAdmin, '/create')
api.add_resource(DetailAdmin, '/detail')
api.add_resource(EditAdmin, '/edit')
api.add_resource(PwdAdmin, '/pwd')
api.add_resource(DeleteAdmin, '/delete')
